import Scene from "src/shape/Scene"
import ToolFrame, { BoxChild } from "src/shape/ToolFrame"
import { Shape } from "src/types/shape"
import { ActionType } from "src/utils/EventSimulator"

class Point {
  x = 0
  y = 0
}

export default class {
  public state: 0 | 1 = 0
  private scene: Scene
  private enable: boolean = false
  private type: 'shape' | 'frame' = 'shape'
  private activedId: string = ''
  private shape!: ToolFrame
  private activeShape?: Shape | null //当前选中形状
  private point = {
    pre: new Point(),
    cur: new Point(),
    tl: new Point(),
    tr: new Point(),
    bl: new Point(),
    br: new Point(),
  }
  private mousemove: any
  private mouseup: any
  constructor(scene: Scene) {
    this.scene = scene
  }
  open() {
    this.state = 1
    this.shape = new ToolFrame({ x: 0, y: 0, widht: 0, height: 0 })

    this.scene.shapes.push(this.shape)
    this.scene.eventSimulator.addListeners(this.shape.getRgbaId(), this.shape.getListeners())
    this.shape.shapeMap.forEach((value, key) => {
      this.scene.IDS.add(key)
    })

    this.mousemove = this.handleMousemove.bind(this)
    this.mouseup = this.handleMouseup.bind(this)
    document.addEventListener('mousemove', this.mousemove)
    document.addEventListener('mouseup', this.mouseup)
  }
  close() {
    this.state = 0
    this.scene.remove(this.shape.getRgbaId())
    this.shape.shapeMap.forEach((value, key) => {
      this.scene.IDS.has(key) && this.scene.IDS.delete(key)
    })
    if(this.activeShape) this.scene.remove(this.shape.getRgbaId())
    this.activeShape = null
    this.scene.activeShape = null

    document.removeEventListener('mousemove', this.mousemove)
    document.removeEventListener('mouseup', this.mouseup)
  }
  // 鼠标移动
  handleMousemove(e: MouseEvent) {
    if (!this.enable) return
    const { activeShape, shape, type, point } = this
    point.cur.x = e.offsetX
    point.cur.y = e.offsetY

    const dx = point.cur.x - point.pre.x
    const dy = point.cur.y - point.pre.y

    if (activeShape) {
      switch (type) {
         // 元素本身
        case 'shape':
          activeShape.props.lateX += dx
          activeShape.props.lateY += dy

          shape.props.lateX += dx
          shape.props.lateY += dy

          shape.props.borderColor = 'rgba(71, 154, 227, 0.5)'
          break
        // 操作框
        case 'frame':
          const x = (shape.props.width - activeShape.props.width) / activeShape.props.width
          const y = (shape.props.height - activeShape.props.height) / activeShape.props.height
          const scaleX = 1 + x || 1
          const scaleY = 1 + y || 1

          // 矩阵变换
          const translate = (moveX = true, moveY = true) => {
            const scale = shape.props.rotation * Math.PI / 180

            let vectorX = 0, vectorY = 0 //向量
            // 横向
            if (moveX && !moveY) {
              vectorX = dx / 2 * Math.cos(scale)
              vectorY = dx / 2 * Math.sin(scale)
            } 
            // 纵向
            else if (!moveX && moveY) {
              vectorX = dy / 2 * Math.sin(-scale)
              vectorY = dy / 2 * Math.cos(-scale)
            } 
            // 横向+纵向
            else if (moveX && moveY) {
              const { width, height } = shape.props

              type position = 'tl' | 'tr' | 'bl' | 'br'
              let center: position, left: position, right: position
              center = left = right = 'tl'
              switch (shape.shapeMap.get(this.activedId)) {
                case BoxChild.topL:
                  center = 'br', left = 'bl', right = 'tr'
                  break
                case BoxChild.topR:
                  center = 'bl', left = 'tl', right = 'br'
                  break
                case BoxChild.bottomL:
                  center = 'tr', left = 'tl', right = 'br'
                  break
                case BoxChild.bottomR:
                  center = 'tl', left = 'bl', right = 'tr'
                  break
              }

              const a = point[right].x - point[center].x
              const b = point[right].y - point[center].y
              const c = point[left].x - point[center].x
              const d = point[left].y - point[center].y

              const angle = Math.atan2(b, a) * 180 / Math.PI
              const angle1 = Math.atan2(d, c) * 180 / Math.PI

              const originx = point[center].x + width * Math.cos(angle * Math.PI / 180)
              const originY = point[center].y + width * Math.sin(angle * Math.PI / 180)
              const originx1 = point[center].x + height * Math.cos(angle1 * Math.PI / 180)
              const originY1 = point[center].y + height * Math.sin(angle1 * Math.PI / 180)

              vectorX = originx1 + (originx - originx1) / 2
              vectorY = originY1 + (originY - originY1) / 2

              // shape.props.x = vectorX
              // shape.props.y = vectorY
              // activeShape.props.x = vectorX
              // activeShape.props.y = vectorY

              return
            }

            shape.props.lateX += vectorX
            shape.props.lateY += vectorY
            activeShape.props.lateX += vectorX
            activeShape.props.lateY += vectorY
          }
          // 操作框控件操作
          switch (shape.shapeMap.get(this.activedId)) {
            case BoxChild.left:

              shape.props.width -= dx
              activeShape.props.scaleX = scaleX
              translate(true, false)
              break
            case BoxChild.right:
              shape.props.width += dx
              activeShape.props.scaleX = scaleX

              translate(true, false)
              break
            case BoxChild.top:
              shape.props.height -= dy
              activeShape.props.scaleY = scaleY

              translate(false, true)
              break
            case BoxChild.bottom:
              shape.props.height += dy
              activeShape.props.scaleY = scaleY

              translate(false, true)
              break
            case BoxChild.topL:
              shape.props.width -= dx
              shape.props.height -= dy
              activeShape.props.scaleX = scaleX
              activeShape.props.scaleY = scaleY

              translate(true, true)
              break
            case BoxChild.topR:
              shape.props.width += dx
              shape.props.height -= dy
              activeShape.props.scaleX = scaleX
              activeShape.props.scaleY = scaleY

              translate(true, true)
              break
            case BoxChild.bottomL:
              shape.props.width -= dx
              shape.props.height += dy
              activeShape.props.scaleX = scaleX
              activeShape.props.scaleY = scaleY

              translate(true, true)
              break
            case BoxChild.bottomR:
              // shape.props.x += dx / 2
              // shape.props.y += dy / 2
              // activeShape.props.x += dx / 2
              // activeShape.props.y += dy / 2
              shape.props.width += dx
              shape.props.height += dy
              activeShape.props.scaleX = scaleX
              activeShape.props.scaleY = scaleY

              translate(true, true)
              break
            case BoxChild.scale:
              const a = point.cur.x - (shape.props.x + shape.props.lateX)
              const b = point.cur.y - (shape.props.y + shape.props.lateY)
              const rotation = Math.atan2(b, a) * 180 / Math.PI + 90

              shape.props.rotation = rotation
              activeShape.props.rotation = rotation
              break
          }
          break
      }

      this.scene.render()
    }

    // 更新坐标
    point.pre.x = e.offsetX
    point.pre.y = e.offsetY
  }
  // 鼠标抬起
  handleMouseup() {
    if (this.enable && this.type == 'shape') {
      this.shape.props.borderColor = 'rgba(71, 154, 227, 1)'
      document.body.style.cursor = 'default'
      this.scene.render()
    }
    this.enable = false
  }
  // 鼠标按下
  handleFrameBox(type: string, id: string, e: MouseEvent) {
    if (this.state == 0 || type != ActionType.Down) return

    const { shapes } = this.scene
    const { shape, point } = this
    // 操作框对象
    if (shape.shapeMap.get(id)) {
      this.type = 'frame'
      this.activedId = id

      point.pre.x = e.offsetX
      point.pre.y = e.offsetY

      // 获取角的坐标
      const getShapePoint = (angle: number) => {
        const { x, y, width, height, rotation } = shape.props
        const diagonal = Math.sqrt(width * width + height * height) / 2
        const originx = x + diagonal * Math.cos((rotation + angle) * Math.PI / 180)
        const originY = y + diagonal * Math.sin((rotation + angle) * Math.PI / 180)
        return {
          x: originx,
          y: originY
        }
      }

      point.tl = getShapePoint(-135)
      point.tr = getShapePoint(-45)
      point.bl = getShapePoint(135)
      point.br = getShapePoint(45)

      this.enable = true
    }
    // 点击空白区域
    else if (this.scene.emptySpace) {
      if (shape) {
        this.scene.remove(shape.getRgbaId())
        this.activeShape = null
        this.scene.activeShape = null
      }
    }
    // 图形对象
    else {
      this.activeShape = null
      this.scene.activeShape = null
      shapes.forEach(shape => {
        shape.actived = false
        if (shape.getRgbaId() == id) {
          this.type = 'shape'
          shape.actived = true
          this.activeShape = shape
          this.scene.activeShape = shape

          // 初始化操作框
          this.shape.setProps((this.activeShape as Shape).props)
          this.scene.shapes.push(this.shape)

          document.body.style.cursor = 'move'
          point.pre.x = e.offsetX
          point.pre.y = e.offsetY
          this.enable = true
        }
      })
    }
    const index = this.scene.historyID.indexOf(shape.getRgbaId())
    if (this.activeShape) {
      this.shape.setProps((this.activeShape as Shape).props)
      if (index == -1) this.scene.historyID.push(shape.getRgbaId())
    } else {
      if (index != -1) this.scene.historyID.splice(index, 1)
    }
    this.scene.render()
  }
}